﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using Shared;

namespace Tui
{
    public abstract partial class BusinessObject<T> where T : BusinessObject<T>, new()
    {
        public class Savior : IDisposable
        {
            internal Savior()
            {
                _bos = BusinessObjectSupport.GetSupporter(typeof(T));
                _cnn = _bos.ConnectionGet();//cleanup on exception
                _resultSet = OpenResultSet();
                _populateResultset = ObjectReaderWriter.GetPopulateResultsetThing</*BusinessObject<*/T/*>*/>(_cnn, _resultSet, _bos);
                _pk = _populateResultset.CreatePrimaryKeyArray();
            }
            private SqlCeResultSet OpenResultSet()
            {
                string tn = _bos.TableName;
                using (SqlCeCommand cmd = new SqlCeCommand(tn, _cnn))
                {
                    cmd.CommandType = System.Data.CommandType.TableDirect;
                    cmd.IndexName = DatabaseInfo.GetPrimaryKeyName(_cnn, tn);
                    return cmd.ExecuteResultSet(ResultSetOptions.Updatable);
                }
            }

            private readonly BusinessObjectSupport _bos;
            private readonly ObjectReaderWriter.PopulateResultset</*BusinessObject<*/T/*>*/> _populateResultset;
            private readonly SqlCeResultSet _resultSet;
            private readonly SqlCeConnection _cnn;
            private readonly object[] _pk;
            internal void Save(BusinessObject<T> businessObject)
            {
                _populateResultset.LoadPrimaryKey(businessObject, _pk);

                if (_resultSet.Seek(DbSeekOptions.FirstEqual, _pk) && _resultSet.Read())
                {
                    _populateResultset.WriteToResultset(_resultSet, businessObject);
                    _resultSet.Update();
                }
                else
                {
                    var nr = _resultSet.CreateRecord();
                    _populateResultset.WriteToNewRecord(nr, businessObject);
                    _resultSet.Insert(nr);
                }
            }


            void IDisposable.Dispose()
            {
                _resultSet.Dispose();
                _bos.ConnectionRelease(_cnn);
            }

            internal bool Delete(BusinessObject<T> businessObject)
            {
                _populateResultset.LoadPrimaryKey(businessObject, _pk);

                if (!_resultSet.Seek(DbSeekOptions.FirstEqual, _pk) || !_resultSet.Read()) return false;

                _resultSet.Delete();
                return true;
            }
        }
    }
}
